package sysmiddleware

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/vueadmin/app/admin/internal/svc"
	sys "github.com/vueadmin/app/admin/sys"
	"github.com/vueadmin/app/admin/sys/sysvalidate"
	"github.com/vueadmin/utils"
	"github.com/vueadmin/utils/conv"
	"github.com/vueadmin/utils/response"
)

type UpdateMenuMiddleware struct {
	svcCtx *svc.ServiceContext
}

func NewUpdateMenuMiddleware(svcCtx *svc.ServiceContext) *UpdateMenuMiddleware {
	return &UpdateMenuMiddleware{
		svcCtx: svcCtx,
	}
}

// 修改数据表中间件
func (p UpdateMenuMiddleware) Handle() gin.HandlerFunc {
	return func(c *gin.Context) {
		var data sys.Menu
		var menu sys.Menu
		if err := utils.BindAndValid(c, &data); err != nil {
			response.Fail(c, err.Error())
			c.Abort()
			return
		}
		if err := new(sysvalidate.MenuValidate).Validate(&data); err != nil {
			response.Fail(c, err.Error())
			c.Abort()
			return
		}
		if sys.System.GetDBTypeByConnect(data.Connect) != "mysql" {
			return
		}
		prefix := sys.System.GetPrefix(data.Connect)

		if err := p.svcCtx.Db.Where("menu_id", data.MenuId).Find(&menu).Error; err != nil {
			panic(err)
		}

		if !conv.IsEmpty(menu.Tablename) && menu.CreateTable == 1 && !conv.IsEmpty(menu.Pk) {
			tablename := prefix + menu.Tablename

			tables := make([]string, 0)
			sys.System.Conn(p.svcCtx, menu.Connect).Raw("show tables").Pluck("Tables_in_mysql", &tables)

			if conv.IsValueInList(tablename, tables) {
				var sqlField = fmt.Sprintf("ALTER TABLE %s CHANGE %s %s INT( 11 ) COMMENT '编号' NOT NULL AUTO_INCREMENT;", prefix+data.Tablename, menu.Pk, data.Pk)
				var sqlTable = fmt.Sprintf("ALTER TABLE %s RENAME TO %s;", tablename, prefix+data.Tablename)

				pk_id := sys.System.GetPkByTable(p.svcCtx, menu.Connect, tablename)
				if pk_id != data.Pk {
					p.svcCtx.Db.Model(&sys.Field{}).Where("menu_id", data.MenuId).Where("field", pk_id).Update("field", data.Pk)
				}

				if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sqlTable).Error; err != nil {
					panic(err)
				}

				if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sqlField).Error; err != nil {
					panic(err)
				}

				if conv.Int(data.PageType) == 2 {
					fields := GetTableFields(p.svcCtx, menu.Connect, tablename)
					if !conv.IsValueInList("name", fields) {
						var sql = fmt.Sprintf("ALTER TABLE `%s` ADD `name` VARCHAR( 50 ) NOT NULL ", tablename)
						if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sql).Error; err != nil {
							panic(err)
						}
					}
					if !conv.IsValueInList("data", fields) {
						var sql = fmt.Sprintf("ALTER TABLE `%s` ADD `data` TEXT NOT NULL AFTER `name`", tablename)
						if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sql).Error; err != nil {
							panic(err)
						}
					}
				}
			} else {
				var sql = fmt.Sprintf(" CREATE TABLE IF NOT EXISTS `%s` ( ", prefix+data.Tablename)
				sql += fmt.Sprintf("`%s` int(11) NOT NULL AUTO_INCREMENT ,PRIMARY KEY (`%s`)) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4", data.Pk, data.Pk)
				if err := sys.System.Conn(p.svcCtx, menu.Connect).Exec(sql).Error; err != nil {
					panic(err)
				}
			}
		}
		c.Set("data", data)
		c.Next()
	}
}

// 获取数据表的所有字段
func GetTableFields(svcCtx *svc.ServiceContext, connect string, tablename string) []string {
	var data []string
	fields, _ := sys.System.GetFullColumns(svcCtx, connect, tablename)
	for _, val := range fields {
		data = append(data, val.Field)
	}
	return data
}
